package com.poizon.infrastructure.idem.config.change.listener;

import cn.hutool.core.util.StrUtil;
import com.poizon.infrastructure.center.config.core.event.listener.ConfigChangeListenerImpl;
import com.poizon.infrastructure.center.config.core.event.strategy.ConfigChangeEventStrategy;
import com.poizon.infrastructure.idem.core.domain.value.config.IdemConstants;
import com.poizon.infrastructure.idem.core.recovery.IdemDbStoreFailover;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

import java.util.Properties;

/**
 * 幂等底层存储配置变更监听
 */
@Slf4j
@ConditionalOnClass(value = {ConfigChangeEventStrategy.class, ConfigChangeListenerImpl.class})
@ConditionalOnBean(value = ConfigChangeListenerImpl.class)
public class IdemDbStoreConfigChangeStrategy implements ConfigChangeEventStrategy {
    /**
     * 尝试从变更的配置文件中获取幂等底层存储配置
     */
    @Override
    public String getChangedProperty(Properties properties) {
        if (properties == null) {
            return null;
        }
        String config = properties.getProperty(IdemConstants.DB_STORE_TYPE_CONFIG);
        return config;
    }

    /**
     * 如果幂等底层存储配置未发生变更,则不处理
     */
    @Override
    public Boolean support(Properties properties) {
        String config = getChangedProperty(properties);
        return StrUtil.isNotBlank(config);
    }

    /**
     * 触发幂等底层存储配置变更
     */
    @Override
    public void configChange(Properties properties) {
        if (properties == null) {
            return;
        }
        // todo: 切换的过程中,需要对幂等操作加锁,暂停业务,防止部分业务数据在旧存储中,部分在新存储中

        // 获取变更后的新存储
        String newDbStoreType = getChangedProperty(properties);
        if (StrUtil.isBlank(newDbStoreType)) {
            return;
        }

        // 获取变更前存储
        String oldDbStoreType = IdemConstants.IDEM_DB_STORE_TYPE;
        // 存储未发生变更
        if (StrUtil.equals(newDbStoreType, oldDbStoreType)) {
            log.info("[通用幂等框架] 存储实现未发生变更");
            return;
        }

        // 尝试变更底层存储
        Boolean status = IdemDbStoreFailover.changeIdemDbStoreInstantly(newDbStoreType);

        if (status) {
            log.info("[通用幂等框架] 变更底层存储类型 {} -> {} 成功", oldDbStoreType, newDbStoreType);
        } else {
            log.error("[通用幂等框架] 变更底层存储类型 {} -> {} 失败", oldDbStoreType, newDbStoreType);
        }
    }
}
